/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package openfireconnection.group.impl;

import batis.MyBatisSqlSessionFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import openfireconnection.group.ManejadorGroups;
import openfireconnection.group.model.GroupModel;
import openfireconnection.group.model.MemberModel;
import openfireconnection.group.model.PropertyModel;
import org.apache.ibatis.session.SqlSession;

/**
 * Implementación de la interfaz para el manejo de grupos de OpenFire
 * @author Miguel y Juanan - Telecor
 */
public class ManejadorGroupsImpl implements ManejadorGroups {
    private SqlSession session = null;
    
    /**
     * Constructor de la clase que implementa los métodos para el manejo de
     * grupos en OpenFire
     */
    public ManejadorGroupsImpl() {
        session = MyBatisSqlSessionFactory.getSqlSessionFactory().openSession();
    }
    
    /**
     * Obtiene los grupos de OpenFire
     * @return Devuelve un array con los grupos
     */
    @Override
    public ArrayList<GroupModel> getGroups() {
        return session.getMapper(ManejadorGroups.class).getGroups();
    }
    
    /**
     * Obtiene un grupo de OpenFire
     * @param groupName Nombre del grupo que se va a obtener
     * @return Devuelve un grupo, sino se encuentra devuelve null
     */
    @Override
    public GroupModel getGroup(String groupName) {
        return session.getMapper(ManejadorGroups.class).getGroup(groupName);
    }

    /**
     * Devuelve los nombres de los grupos de OpenFire
     * @return Devuelve un arraylist con los nombres
     */
    @Override
    public ArrayList<String> getGroupsNames() {
        return session.getMapper(ManejadorGroups.class).getGroupsNames();
    }
    
    /**
     * Devuelve los miembros de un grupo de OpenFire
     * @param groupName Nombre del grupo de OpenFire
     * @return Devuelve un ArrayList con los miembros del grupo de OpenFire
     */
    @Override
    public ArrayList<MemberModel> getGroupMembers(String groupName) {
        return session.getMapper(ManejadorGroups.class).getGroupMembers(groupName);
    }
    
    /**
     * Devuelve los nombres de los miembros de un grupo de OpenFire
     * @param groupName Nombre del grupo de OpenFire
     * @return Devuelve un ArrayList con los nombres de los miembros del grupo
     */
    @Override
    public ArrayList<String> getGroupMembersName(String groupName) {
        return session.getMapper(ManejadorGroups.class).getGroupMembersName(groupName);
    }
    
    /**
     * Devuelve el número de grupos existentes en OpenFire
     * @return Devuelve el número de OpenFire
     */
    @Override
    public int getCountGroups() {
        return session.getMapper(ManejadorGroups.class).getCountGroups();
    }

    /**
     * Obtiene la descripción de un grupo de OpenFire
     * @param groupName Nombre del grupo de OpenFire
     * @return Devuelve la descripción del grupo de OpenFire
     */
    @Override
    public String getGroupDescription(String groupName) {
        return session.getMapper(ManejadorGroups.class).getGroupDescription(groupName);
    }
    
    /**
     * Comprueba si existe un grupo de OpenFire
     * @param groupName Nombre del grupo de OpenFire
     * @return Devuelve Verdad si existe sino Falso
     */
    public boolean existGroup(String groupName) {
        return getGroup(groupName) != null;
    }

    /**
     * Devuelve los nombres de los grupos compartidos de OpenFire
     * @return Devuelve un ArrayList con los grupos compartidos de OpenFire
     */
    @Override
    public ArrayList<String> getGroupsSharedName() {
        return session.getMapper(ManejadorGroups.class).getGroupsSharedName();
    }

    /**
     * Obtiene la lista de grupo a los que comparte el grupo de OpenFire
     * @param groupName Nombre del grupo de OpenFire
     * @return Devuelve 1 si se ha obtenido la lista, 0 sino
     */
    @Override
    public String getGroupSharedNames(String groupName) {
        return session.getMapper(ManejadorGroups.class).getGroupSharedNames(groupName);
    }
    
    public boolean isSharedGroup(String groupName) {
        Map map = new HashMap<String, String>();
        map.put("groupName", groupName);
        map.put("propertyName", "sharedRoster.showInRoster");
        
        String valorPropiedad = getGroupProperty(map);
        
        return valorPropiedad != null && !valorPropiedad.equals("nobody");
    }
    
    public void enableSharedGroups(String groupName, String nombreCompartido) {
        Map map = new HashMap<String, String>();
        map.put("groupName", groupName);
        map.put("propertyName", "sharedRoster.showInRoster");
        map.put("propValue", "onlyGroup");
        updateGroupProperty(map);

        Map map2 = new HashMap<String, String>();
        map2.put("groupName", groupName);
        map2.put("propertyName", "sharedRoster.displayName");
        map2.put("propValue", nombreCompartido);
        updateGroupProperty(map2);
    }
    
    public void disableSharedGroup(String groupName) {
        Map map = new HashMap<String, String>();
        map.put("groupName", groupName);
        map.put("propertyName", "sharedRoster.showInRoster");
        map.put("propValue", "nobody");
        updateGroupProperty(map);
        
        Map map2 = new HashMap<String, String>();
        map2.put("groupName", groupName);
        map2.put("propertyName", "sharedRoster.displayName");
        map2.put("propValue", "");
        updateGroupProperty(map2);
    }
    
    public void enableShareAll(String groupName, String nombreCompartido) {
        Map map = new HashMap<String, String>();
        map.put("groupName", groupName);
        map.put("propertyName", "sharedRoster.showInRoster");
        map.put("propValue", "everybody");
        updateGroupProperty(map);

        Map map2 = new HashMap<String, String>();
        map2.put("groupName", groupName);
        map2.put("propertyName", "sharedRoster.displayName");
        map2.put("propValue", nombreCompartido);
        updateGroupProperty(map2);
    }
    
    public void disabledSharedNames(String groupName) {
        if(isSharedGroup(groupName)) {
            //Dejamos vacía la propiedad
            Map map = new HashMap<String, String>();
            map.put("groupName", groupName);
            map.put("propertyName", "sharedRoster.groupList");
            map.put("sharedRoster.groupList", groupName);
            map.put("propValue", "");
        }
    }
    
    /**
     * Añade un grupo a la lista de grupos compartidos del grupo de OpenFire
     * @param map Recibe un Map con la siguiente sintaxis:
     *  groupName Nombre del grupo de OpenFire
     *  groupNameShare Nombre del grupo que se añade para compartir
     * @return Devuelve 1 si se ha añadido el grupo, sino 0
     */
    public int addGroupShared(Map map) {
        if(existGroup((String)map.get("groupNameShare"))
                && existGroup((String)map.get("groupName"))
                && isSharedGroup((String)map.get("groupName"))) {
            String gruposCompartidos = getGroupSharedNames(
                    (String)map.get("groupName"));
            
            String[] grupos = gruposCompartidos.split(",");
            
            String nuevaListaGrupos = "";
            for(int i=0; i<grupos.length; i++) {
                nuevaListaGrupos += grupos[i] + ",";
            }
            nuevaListaGrupos += (String)map.get("groupNameShare");
            
            Map mapaPropiedad = new HashMap<String, String>();
            mapaPropiedad.put("groupName", (String)map.get("groupName"));
            mapaPropiedad.put("propertyName", "sharedRoster.groupList");
            mapaPropiedad.put("propValue", nuevaListaGrupos);
            return session.getMapper(ManejadorGroups.class).updateGroupProperty(
                    mapaPropiedad);
        } else {
            return 0;
        }
    }
    
    /**
     * Quita un grupo de la lista de grupos compartidos del grupo de OpenFire
     * @param map Recibe un Map con la siguiente sintaxis:
     *  groupName Nombre del grupo de OpenFire
     *  groupNameShare Nombre del grupo que se quita para compartir
     * @return Devuelve 1 si se ha quitado el grupo, sino 0
     */
    public int removeGroupShared(Map map) {
        if(existGroup((String)map.get("groupNameShare"))
                && existGroup((String)map.get("groupName"))) {
            String gruposCompartidos = getGroupSharedNames(
                    (String)map.get("groupName"));
            
            String[] grupos = gruposCompartidos.split(",");
            
            
            String nuevaListaGrupos = "";
            boolean encontrado = false;
            for(int i=0; i<grupos.length; i++) {
                if(grupos[i].equals((String)map.get("groupNameShare"))) {
                    encontrado = true;
                    
                } else {
                    if(i + 1 == grupos.length) {
                        nuevaListaGrupos += grupos[i];
                    } else {
                        nuevaListaGrupos += grupos[i] + ",";
                    }
                }
            }
            
            if(!encontrado) {
                return 0;
            } else {
                Map mapaPropiedad = new HashMap<String, String>();
                mapaPropiedad.put("groupName", (String)map.get("groupName"));
                mapaPropiedad.put("propertyName", "sharedRoster.groupList");
                mapaPropiedad.put("propValue", nuevaListaGrupos);
                return session.getMapper(ManejadorGroups.class).updateGroupProperty(
                        mapaPropiedad);
            }
        } else {
            return 0;
        }
    }
    
    /**
     * Devuelve la propiedad de un grupo de OpenFire
     * @param map Recibe un Map con la siguiente sintaxis:
     *  groupName -> nombre del grupo
     *  propertyName -> propiedad que se quiere obtener
     * @return 
     */
    @Override
    public String getGroupProperty(Map map) {
        return session.getMapper(ManejadorGroups.class).getGroupProperty(map);
    }

    /**
     * Actualiza el nombre de un grupo de OpenFire
     * @param map Recibe un Map con la siguiente sintaxis:
     *  groupName -> Nombre del grupo
     *  groupNameNew -> Nuevo nombre del grupo
     * @return 
     */
    @Override
    public int updateGroupName(Map map) {
        return session.getMapper(ManejadorGroups.class).updateGroupName(map);
    }
    
    /**
     * Actualiza la descripción de un grupo de OpenFire
     * @param membreModel Grupo que va a ser actualizado
     * @return Devuelve 1 si la actualización es correcta, sino 0
     */
    @Override
    public int updateGroupDescription(MemberModel memberModel) {
        if(existGroup(memberModel.getGroupName())) {
            return session.getMapper(ManejadorGroups.class).updateGroupDescription(memberModel);
        } else {
            return 0;
        }
    }

    /**
     * Actualiza el miembro de un grupo de OpenFire
     * @param memberModel Recibe el miembro de un grupo que va a ser actualizado
     * @return Devuelve 1 si la actualización es correcta, sino 0
     */
    @Override
    public int updateGroupMember(MemberModel memberModel) {
        if(existGroup(memberModel.getGroupName())) {
            return session.getMapper(ManejadorGroups.class).updateGroupMember(memberModel);
        } else {
            return 0;
        }
    }

    /**
     * Actualiza la propiedad de un grupo.
     * @param map Recibe un Map con la siguiente sintaxis:
     *  groupName: Nombre del grupo
     *  propertyName: Nombre de la propiedad
     *  propValue: Valor de la propiedad actualizado
     * @return Devuelve 1 si la actualización es correcta, sino 0
     */
    @Override
    public int updateGroupProperty(Map map) {
        if(existGroup((String)map.get("groupName"))) {
            return session.getMapper(ManejadorGroups.class).updateGroupProperty(map);
        } else {
            return 0;
        }
    }

    /**
     * Comprueba si existe un miembro de un grupo
     * @param memberModel Miembro de un grupo
     * @return Devuelve Verdad si existe, sino Falso
     */
    public boolean isMemberExists(MemberModel memberModel) {
        ArrayList<MemberModel> members = getGroupMembers(memberModel.getGroupName());
        
        if(members != null) {
            return members.contains(memberModel);
        } else {
            return false;
        }
    }
    
    /**
     * Inserta un miembro en un grupo de OpenFire
     * @param memberModel Recibe un miembro de OpenFire
     * @return Devuelve 1 si la inserción es correcta, sino 0
     */
    @Override
    public int insertGroupMember(MemberModel memberModel) {
        if(existGroup(memberModel.getGroupName())) {
            try {
                //Si el miembro no está insertado
                if(!isMemberExists(memberModel)) {
                    return session.getMapper(ManejadorGroups.class).insertGroupMember(memberModel);
                } else {
                    return 0;
                }
            } catch(Exception e) {
                return 0;
            }
        } else {
            return 0;
        }
    }

    /**
     * Inserta un grupo en OpenFire
     * @param groupModel Recibe un grupo de OpenFire
     * @return Devuelve 1 si la inserción es correcta, sino 0
     */
    @Override
    public int insertGroup(GroupModel groupModel) {
        if(!existGroup(groupModel.getName())) {
            try {
                int gruposMetidos = session.getMapper(ManejadorGroups.class).insertGroup(groupModel);
                
                ArrayList<PropertyModel> propertys = groupModel.getPropertys();
                for(PropertyModel property : propertys) {
                    Map mapProperty = new HashMap<String, String>();
                    mapProperty.put("groupName", groupModel.getName());
                    mapProperty.put("propertyName", property.getNameProperty());
                    mapProperty.put("valueProperty", property.getValueProperty());
                    insertGroupProperty(mapProperty);
                }
                
                ArrayList<MemberModel> members = groupModel.getMembers();
                for(MemberModel member : members) {
                    insertGroupMember(member);
                }
                
                return gruposMetidos;
            } catch(Exception e) {
                return 0;
            }
        } else {
            return 0;
        }
    }

    /**
     * Inserta la propiedad de un grupo en OpenFire
     * @param map Recibe un Map con la siguiente sintaxis:
     *  groupName -> Nombre del grupo de OpenFire
     *  propertyName -> Nombre de la propiedad de OpenFire
     *  valueProperty -> Valor de la propiedad
     * @return Devuelve 1 si la inserción es correcta, sino 0
     */
    @Override
    public int insertGroupProperty(Map map) {
        if(existGroup((String)map.get("groupName"))) {
            return session.getMapper(ManejadorGroups.class).insertGroupProperty(map);
        } else {
            return 0;
        }
    }

    /**
     * Borra un grupo de OpenFire
     * @param groupModel Grupo que va a ser borrado de OpenFire
     * @return Devuelve 1 si se ha borrado correctamente, sino 0
     */
    @Override
    public int deleteGroup(GroupModel groupModel) {
        if(existGroup(groupModel.getName())) {
            try {
                String nombreGrupo = groupModel.getName();
                int del = session.getMapper(ManejadorGroups.class).deleteGroup(groupModel);
                
                ArrayList<MemberModel> members = groupModel.getMembers();
                
                //Borramos los miembros
                for(MemberModel member : members) {
                    deleteGroupMember(member);
                }
                
                //Borramos las propiedades
                deletePropertys(nombreGrupo);
                
                
                return del;
            } catch(Exception e) {
                return 0;
            }
        } else {
            return 0;
        }
    }

    /**
     * Borra un miembro de un grupo de OpenFire
     * @param memberModel Miembro de OpenFire a ser borrado
     * @return Devuelve 1 si se ha borrado correctamente, sino 0
     */
    @Override
    public int deleteGroupMember(MemberModel memberModel) {
        try {
            return session.getMapper(ManejadorGroups.class).deleteGroupMember(memberModel);
        } catch(Exception e) {
            return 0;
        }
    }
    
    /**
     * Borra las propiedades de un grupo de OpenFire
     * @param groupName Nombre del grupo de OpenFire
     * @return Devuelve el número de propiedades borradas
     */
    @Override
    public int deletePropertys(String groupName) {
        try {
            return session.getMapper(ManejadorGroups.class).deletePropertys(groupName);
        } catch(Exception e) {
            return 0;
        }
    }
    
    
}
